package cn.wolfcode.shiro;

import cn.wolfcode.domain.Employee;
import cn.wolfcode.exception.LogincException;
import cn.wolfcode.service.IEmployeeService;
import cn.wolfcode.service.IPermissionService;
import cn.wolfcode.service.IRoleService;
import cn.wolfcode.util.UserContext;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

//自定义CRM数据源
@Component
public class CrmRealm extends AuthorizingRealm {
    @Autowired
    private IEmployeeService employeeService;

    @Autowired
    private IPermissionService permissionService;

    @Autowired
    private IRoleService roleService;

    //提供授权信息
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //测试缓存
        System.out.println("================");
        //1.获取当前登录的员工的对象,获取员工id
        Employee currentUser = UserContext.getCurrentUser();
        Long employeeId = currentUser.getId();
        //同上效果获取登录员工
        //Employee employee = (Employee)principals.getPrimaryPrincipal();

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //2.查询数据库该员工的拥有的角色和权限数据
        //3.设置当前登录用户拥有的角色和权限数据
        //设置权限数据
        if (!currentUser.isAdmin()){ //如果不是管理员,就需要查询
            List<String> expressions = permissionService.selectExpressionByEmpId(employeeId);
            info.addStringPermissions(expressions);
            //设置角色数据
            List<String> sns = roleService.selectSnByEmpId(employeeId);
            info.addRoles(sns);
        }else{
           /* 权限拦截的功能是shiro来做的,不知道Employee的属性的意义,
            它还是按照权限表达式来判断,可以给通配符*/
           info.addStringPermission("*:*");
           info.addRole("admin");//管理员的角色
        }





        return info;
    }

    //提供认证信息
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //当前的方法如果直接返回null,shiro会自动抛出账号不存在的异常
        //如果返回的结果不为null,shiro会自动从返回的对象中获取到真实的密码,再与token去对比

        //1.获取令牌中的用户名(前端传来的)
        String username = (String) token.getPrincipal();
        //2.查询数据库中是否存在该员工(模拟数据库中的数据)
        Employee employee = employeeService.selectByName(username);
        //3.如果不存在,直接返回null
        if (employee!=null){
            if (employee.getPassword().equals("")){
                throw new AuthenticationException("数据库密码为空");

            }

            if (!employee.isStatus()){
                throw new DisabledAccountException("禁用傻逼");
            }



            //如果存在,返回 SimpleAuthenticationInfo 对象
            //身份信息可以在任意地方获取到,用来跟subject绑定在一起的
            //在项目中是就直接传入员工对象,跟subject绑定在一起,方便我们后续在任意地方获取当前登录的员工对象
            //传入当前数据源的名字,对于我们现在的项目没有作用,一般是一个项目中有多个数据源时,需要做标志,代表数据是从哪个数据源查出来的
            return new SimpleAuthenticationInfo(employee,employee.getPassword(),this.getName());
        }
        return null;
    }
}
